﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Kokomo.PeInspector.Reflection.Disassembly;

namespace Kokomo.PeInspector.Reflection
{
	/// <summary>
	/// Implements functionality for code generators that
	/// use braces to denote lexical blocks.
	/// </summary>
	/// <seealso cref="OpenBlock"/>
	/// <seealso cref="CloseBlock"/>
	/// <seealso cref="OpenInlineBlock"/>
	/// <seealso cref="CloseInlineBlock"/>
	public abstract class BracedCodeDocumentBuilder : CodeDocumentBuilder
	{
		/// <summary>
		/// Initializes a new instance of <see cref="BracedCodeDocumentBuilder"/>.
		/// </summary>
		/// <param name="writer">The underlying <see cref="ICodeWriter"/>.</param>
		/// <param name="memberContext">The member context.</param>
		/// <param name="disassemblerDelegate">The delegate providing disassembly of a method</param>
		/// <param name="importedNamespaces">The list of namespaces imported into the context.</param>
		/// <exception cref="ArgumentNullException"><paramref name="writer"/> is <c>null</c>.</exception>
		public BracedCodeDocumentBuilder(
			ICodeWriter writer,
			MemberInfo memberContext,
			Func<MethodBase, MethodDecompilation> disassemblerDelegate,
			string[] importedNamespaces = null
			)
			: base(writer, memberContext, disassemblerDelegate, importedNamespaces)
		{
		}

		#region Blocks
		/// <summary>
		/// Prints an open brace, line break, and increases indent.
		/// </summary>
		public void OpenBlock()
		{
			this.Writer.EnsureNewLine();
			this.WriteText("{");
			this.Writer.Indent();
			this.Writer.WriteLineBreak();
		}
		/// <summary>
		/// Decreases indent level and prints a close brace on a new line, followed by a line break.
		/// </summary>
		public void CloseBlock()
		{
			this.Writer.Outdent();
			this.Writer.EnsureNewLine();
			this.WriteText("}");
			this.Writer.WriteLineBreak();
		}

		/// <summary>
		/// Prints an open brace and increases indent, but does not print a new line.
		/// </summary>
		public void OpenInlineBlock()
		{
			this.WriteText(" { ");
			this.Writer.Indent();
		}

		/// <summary>
		/// Prints a closing brace and decreases indent, but does not print a new line.
		/// </summary>
		public void CloseInlineBlock()
		{
			this.Writer.Outdent();
			this.WriteText(" }");
		}
		#endregion
	}
}
